home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-05 / drivers2.zip / TIARA.ASM < prev    next >
Assembly Source File  |  1992-01-23  |  29KB  |  914 lines

  1. version        equ     3
  2.  
  3. ;******************************************************************************;
  4. ;*                                                                            *;
  5. ;*     File: TiaraFTP.ASM                                                     *;
  6. ;*     Auth: Brian Fisher                                                     *;
  7. ;*           Queens University                                                *;
  8. ;*           Computing and Communications Services                            *;
  9. ;*           Rm 2-50 Dupuis Hall                                              *;
  10. ;*           Kingston Ontario                                                 *;
  11. ;*                                                                            *;
  12. ;*     Date: January 24 1990                                                  *;
  13. ;*                                                                            *;
  14. ;*     Purp: (3C501) Packet driver for Tiara Ethernet Card.                   *;
  15. ;*                                                                            *;
  16. ;*============================================================================*;
  17. ;*     Revs: January 25 1990   V 1.6.0 Clean up code and document.            *;
  18. ;*           Feb     24 1991   V 1.8.2 Gets IRQ and I/O info from MCH POS regs*;
  19. ;*                                                                            *;
  20. ;*============================================================================*;
  21. ;*                                                                            *;
  22. ;*     Thanks, Mehdi Safipour, of Tiara Computer Systems, who supplied the    *;
  23. ;*     programming manual and examples.                                       *;
  24. ;*                                                                            *;
  25. ;*============================================================================*;
  26. ;*                                                                            *;
  27. ;*     Logic -                                                                *;
  28. ;*                                                                            *;
  29. ;*     Initialization - classic, by-the-book initialization, with one         *;
  30. ;*     exception:  The manual didn't mention the fact that receive            *;
  31. ;*     interrupts will not always work unless the receive buffer is           *;
  32. ;*     vacuumed.                                                              *;
  33. ;*                                                                            *;
  34. ;*     Byte/Word I/O mode was determined by code ruthlessly copied from       *;
  35. ;*     NI5010.ASM, auth: Russ Nelson.                                         *;
  36. ;*                                                                            *;
  37. ;*     Transmit-no surprises, data goes whoosh]                               *;
  38. ;*                                                                            *;
  39. ;*     Receive-interrupt driven receive makes upcalls to inform the ULP of    *;
  40. ;*     its status.  The 14 byte ethernet header is copied from the card to    *;
  41. ;*     a temporary buffer, to determine the ether-type.  Recv_find is called  *;
  42. ;*     to acquire a buffer from the ULP.  If no buffer, the packet is dropped.*;
  43. ;*     If a buffer is acquired, the packet is copied into it, and recv_copy   *;
  44. ;*     informs the ULP that the data is there.                                *;
  45. ;*                                                                            *;
  46. ;******************************************************************************;
  47. ;
  48.  
  49. DLCR_XMIT_STAT EQU     0               ; EtherStar I/O Register offsets
  50. DLCR_XMIT_MASK EQU     1
  51. DLCR_RECV_STAT EQU     2
  52. DLCR_RECV_MASK EQU     3
  53. DLCR_XMIT_MODE EQU     4
  54. DLCR_RECV_MODE EQU     5
  55. DLCR_ENABLE    EQU     6
  56. DLCR_TDR_LOW   EQU     7
  57. DLCR_NODE_ID   EQU     8
  58. DLCR_TDR_HIGH  EQU     0FH
  59. BMPR_MEM_PORT  EQU     10H
  60. BMPR_PKT_LEN   EQU     12H
  61. BMPR_DMA_ENABLE EQU    14H
  62. PROM_ID        EQU     18H
  63. TMST           EQU     80h
  64. TMT_OK         EQU     80h
  65. BUF_EMPTY      EQU     40h
  66. card_disable   equ     80h             ; written to DLCR_ENABLE to disable card
  67. card_enable    equ     0h              ; written to DLCR_ENABLE to enable card
  68. clear_status   equ     00001111B       ; used to clear status info
  69. ;
  70. ;                      !!!!!!!!--------
  71. ;                      !!!!!!!+--------CLEAR BUS WRITE ERROR
  72. ;                      !!!!!!+---------CLEAR 16 COLLISION
  73. ;                      !!!!!+----------CLEAR COLLISION
  74. ;                      !!!!+-----------CLEAR UNDERFLOW
  75. ;                      !!!+------------NC
  76. ;                      !!+-------------NC
  77. ;                      !+--------------NC
  78. ;                      +---------------NC
  79. ;
  80. no_tx_irqs      equ     0              ; written to clear transmit IRQs
  81. clr_rcv_status  equ     0CFh           ; clears receive status
  82. en_rcv_irqs     equ     10000000B      ; enable receive interrupts
  83. ;
  84. ;                      !!!!!!!!--------
  85. ;                      !!!!!!!+--------ENABLE OVERFLOW
  86. ;                      !!!!!!+---------ENABLE CRC
  87. ;                      !!!!!+----------ENABLE ALIGN
  88. ;                      !!!!+-----------ENABLE SHORT PKT
  89. ;                      !!!+------------DISABLE REMOTE RESET
  90. ;                      !!+-------------RESERVED
  91. ;                      !+--------------RESERVED
  92. ;                      +---------------ENABLE PKT READY
  93. ;
  94. xmit_mode       equ     00000010B
  95. ;                       !!!!!!!!---------ENABLE CARRIER DETECT
  96. ;                       !!!!!!!+---------DISABLE LOOPBACK
  97. ;
  98. ;
  99. recv_mode       equ     00000010B                 ; set receive mode
  100. ;
  101. ;                       !!!!!!!!---------ACCEPT ALL PACKETS
  102. ;                       !!!!!!!+---------ACCEPT PHYSICAL, MULTICAST, AND
  103. ;                       !!!!!!+----------BROADCAST PACKETS
  104. ;                       !!!!!+-----------DISABLE REMOTE RESET
  105. ;                       !!!!+------------DISABLE SHORT PACKETS
  106. ;                       !!!+-------------USE 6 BYTE ADDRESS
  107. ;                       !!+--------------NC
  108. ;                       !+---------------NC
  109. ;                       +----------------DISABLE CRC TEST MODE
  110.  
  111. debug    = 0
  112.  
  113.     include defs.asm
  114.  
  115. code segment word public
  116.     assume  cs:code, ds:code
  117.  
  118.     public  int_no
  119. int_no    db      3,0,0,0            ;must be four bytes long for get_number
  120. io_adr    dw    300h,0            ; default I/O address
  121. is_186    db      0            ; set to 1 if 186, 286, 386 word mode
  122.  
  123.     public    driver_class, driver_type, driver_name, driver_function, parameter_list
  124. driver_class    db      BLUEBOOK,IEEE8023,0    ;from the packet spec
  125. driver_type    db      1        ;from the packet spec
  126. driver_name    db      'TiaraFTP',0    ;name of the driver.
  127. driver_function    db    2
  128. parameter_list    label    byte
  129.     db    1    ;major rev of packet driver
  130.     db    9    ;minor rev of packet driver
  131.     db    14    ;length of parameter list
  132.     db    EADDR_LEN    ;length of MAC-layer address
  133.     dw    GIANT    ;MTU, including MAC headers
  134.     dw    MAX_MULTICAST * EADDR_LEN    ;buffer size of multicast addrs
  135.     dw    0    ;(# of back-to-back MTU rcvs) - 1
  136.     dw    0    ;(# of successive xmits) - 1
  137. int_num    dw    0    ;Interrupt # to hook for post-EOI
  138.             ;processing, 0 == none,
  139.  
  140.     public  rcv_modes
  141. rcv_modes    dw    7        ;number of receive modes in our table.
  142.         dw    0               ;There is no mode zero
  143.         dw    rcv_mode_1
  144.         dw    0
  145.         dw    rcv_mode_3
  146.         dw    0        ;haven't set up perfect filtering yet.
  147.         dw    0
  148.         dw    rcv_mode_6
  149.  
  150.  
  151. ;
  152. ;      Receive Packet Header Buffer: Required because addresses and e-type
  153. ;      must be read from Tiara card before upcall to find a buffer can be
  154. ;      made.  Need the number of bytes, and the e-type for the call...
  155. ;
  156. ether_buff    db    EADDR_LEN  dup(?)
  157.         db    EADDR_LEN  dup(?)
  158. ether_type    db    4 dup(?)
  159. usr_ptr        dd    ?                 ; temp storage or recv_buff ptr
  160.  
  161. writebport  macro   from_base,value
  162.     mov    dx,cs:[io_adr]        ; write byte value to port
  163.     add    dx,from_base
  164.     mov    al,value
  165.     out    dx,al
  166.     endm
  167.  
  168. ;sends $ terminated string to screen
  169. print$ macro   string
  170.     mov    ah,9
  171.     mov    dx,offset &string&    ; print $ terminated string
  172.     int    21h
  173.     endm
  174.  
  175. mark           = 0F90h                 ; marker debug pos on screen 25
  176.  
  177. marker  macro   st,nd
  178.   IF  debug NE 0                       ; do marker if debug <> 0
  179.       pushf                            ; show 2 char marker on
  180.       push es                          ; 25th line, 1st column
  181.       push ax
  182.       mov  ax,0B800h
  183.       mov  es,ax
  184.       mov  al,'&st&'
  185.       mov  byte ptr es:[mark],al
  186.       mov  al,byte ptr es:[mark+1]     ; get color value
  187.       inc  al
  188.       and  al,0Fh
  189.       or   al,1
  190.       mov  byte ptr es:[mark+1],al     ; advance it to show activity
  191.       mov  al,'&nd'
  192.       mov  byte ptr es:[mark+2],al
  193.       mov  al,byte ptr es:[mark+3]
  194.       inc  al
  195.       and  al,0Fh
  196.       or   al,1
  197.       mov  byte ptr es:[mark+3],al
  198.       pop  ax
  199.       pop  es
  200.       popf
  201.     ENDIF
  202.   endm
  203.  
  204.     public    as_send_pkt
  205. ; The Asynchronous Transmit Packet routine.
  206. ; Enter with es:di -> i/o control block, ds:si -> packet, cx = packet length,
  207. ;   interrupts possibly enabled.
  208. ; Exit with nc if ok, or else cy if error, dh set to error number.
  209. ;   es:di and interrupt enable flag preserved on exit.
  210. as_send_pkt:
  211.     ret
  212.  
  213.     public    drop_pkt
  214. ; Drop a packet from the queue.
  215. ; Enter with es:di -> iocb.
  216. drop_pkt:
  217.     assume    ds:nothing
  218.     ret
  219.  
  220.     public    xmit
  221. ; Process a transmit interrupt with the least possible latency to achieve
  222. ;   back-to-back packet transmissions.
  223. ; May only use ax and dx.
  224. xmit:
  225.     assume    ds:nothing
  226.     ret
  227.  
  228.  
  229.     public    send_pkt
  230. send_pkt:
  231. ;enter with ds:si -> packet, cx = packet length.
  232. ;exit with nc if ok, pr else cy if error, dh set to error number.
  233.  
  234.               assume  ds:nothing
  235.               marker  T,X
  236.               inc     cx
  237.               and     cx,not 1                ; round to nearest even number
  238.               cmp     cx,RUNT                 ; big enough?
  239.               jae     send_runt_ok
  240.               mov     cx,RUNT                 ; at least runt!
  241. send_runt_ok:
  242.               cmp     cx,GIANT                ; small enough?
  243.               jle     send_size_ok
  244.               stc                             ; Error
  245.               ret
  246. send_size_ok:
  247.               push    cx
  248.               shr     cx,1                    ; words to send
  249. ;
  250. ;      8086/8088 byte mode send
  251. ;
  252.               mov     dx,cs:[io_adr]
  253.               add     dx,BMPR_MEM_PORT
  254.               cmp     cs:is_186,0  ; use BYTE or WORD mode?
  255.               jne     send_w_mode
  256.               cld
  257.  xb:
  258.               lodsw                           ; load word, ind ds:si
  259.               out     dx,al
  260.               xchg    ah,al
  261.               out     dx,al
  262.               loop    xb                      ; set packet length (byte mode)
  263.               pop     ax
  264.               or      ah,TMST
  265.               mov     dx,cs:[io_adr]
  266.               add     dx,BMPR_PKT_LEN
  267.               out     dx,al                   ; write BMPR2, then BMPR3 to
  268.               xchg    al,ah                   ; initiate byte mode transmit
  269.               inc     dx
  270.               out     dx,al
  271.               jmp     wait_tmt_ok
  272. send_w_mode:
  273.               cld
  274.               rep
  275.     db    0f3h, 06fh    ;masm 4.0 doesn't grok "rep outsw"
  276.               pop     ax
  277.               or      ah,TMST
  278.               mov     dx,cs:[io_adr]
  279.               add     dx,BMPR_PKT_LEN
  280.               out     dx,ax
  281. wait_tmt_ok:
  282.               xor     cx,cx
  283.               mov     dx,cs:[io_adr]
  284.               IF DLCR_XMIT_STAT NE 0
  285.                  add     dx,DLCR_XMIT_STAT
  286.               ENDIF
  287. wait_tmt:
  288.               in      al,dx            ; read status register until timeout...
  289.               test    al,TMT_OK
  290.               jnz     send_ok
  291.               loop    wait_tmt
  292.               stc
  293.               ret
  294. send_ok:
  295.               clc
  296.               ret
  297. public  get_address
  298. get_address:
  299.                                             ;get the address on the interface.
  300.     ;enter with es:di -> place to get the address, cx = size of address buffer
  301.     ;exit with nc, cx = actual size of address, or cy if buffer not big enough
  302.     ;
  303.               assume  ds:code
  304.               cmp     cx,EADDR_LEN                   ; enough room for address?
  305.               jge     get_adr_ok
  306.               stc
  307.               ret
  308. get_adr_ok:
  309.               mov     cx,EADDR_LEN
  310.               mov     dx,cs:[io_adr]         ; get address from PROM
  311.               add     dx,PROM_ID
  312.               cld
  313. get_adr:
  314.               in      al,dx
  315.               inc     dx
  316.               stosb
  317.               loop    get_adr
  318.               mov     cx,EADDR_LEN
  319.               clc
  320.               ret
  321.  
  322.  
  323.     public  set_address
  324. set_address:
  325. ;enter with ds:si -> Ethernet address,CX = length of address.
  326. ;exit with nc if okay, or cy, dh=error if any errors.
  327.     assume    ds:nothing
  328.     ret
  329.  
  330.  
  331. rcv_mode_1:
  332.     writebport    DLCR_RECV_MODE,0    ; don't receive any packets
  333.     ret
  334.  
  335.  
  336. rcv_mode_3:
  337.     writebport    DLCR_RECV_MODE,2    ; receive mine, broads, and multis.
  338.     ret
  339.  
  340.  
  341. rcv_mode_6:
  342.     writebport    DLCR_RECV_MODE,3    ; receive all packets.
  343.     ret
  344.  
  345.  
  346.     public  set_multicast_list
  347. set_multicast_list:
  348. ;enter with es:di ->list of multicast addresses, cx = number of bytes.
  349. ;return nc if we set all of them, or cy,dh=error if we didn't.
  350.  
  351.     mov     dh,NO_MULTICAST
  352.     stc
  353.     ret
  354.  
  355.     public  get_multicast_list
  356. get_multicast_list:
  357. ;return with nc, es:di ->list of multicast addresses, cx = number of bytes.
  358. ;return cy, NO_ERROR if we don't remember all of the addresses ourselves.
  359. ;return cy, NO_MULTICAST if we don't implement multicast.
  360.  
  361.     mov     dh,NO_MULTICAST
  362.     stc
  363.     ret
  364.  
  365.     public    terminate
  366. terminate:
  367.     writebport    DLCR_RECV_MODE,0    ; don't receive any packets
  368.     ret
  369.  
  370.     public  reset_interface
  371. reset_interface:                       ;reset the interface.
  372.     assume  ds:code
  373.     ret
  374.  
  375. ;called when we want to determine what to do with a received packet.
  376. ;enter with cx = packet length, es:di -> packet type, dl = packet class.
  377.     extrn   recv_find: near
  378.  
  379. ;called after we've copied the packet into the buffer.
  380. ;enter with ds:si ->the packet, cx = length of the packet.
  381.     extrn   recv_copy: near
  382.  
  383.     extrn   count_in_err: near
  384.     extrn   count_out_err: near
  385.  
  386.     public  recv
  387. recv:
  388. ;called from the recv isr.  All registers have been saved, and ds=cs.
  389. ;Upon exit, the interrupt will be acknowledged.
  390.  
  391.     assume  ds:code
  392.     marker  R,X
  393.  
  394. ;clear receive masks to prevent further IRQs
  395.  
  396.     writebport    DLCR_RECV_MASK,0
  397.     cli
  398. recv_0:
  399.     mov     ax,cs
  400.     mov     ds,ax
  401.     writebport      DLCR_RECV_STAT,clr_rcv_status
  402.  
  403. ;are there any packets to read?
  404.  
  405.     mov     dx,cs:[io_adr]
  406.     add     dx,DLCR_RECV_MODE
  407.     in      al,dx
  408.     test    al,BUF_EMPTY
  409.     jz      recv_1                    ; 0 if at least one valid pkt..
  410.     jmp     recv_99
  411.  
  412. ;yes, read out a receive packet...
  413.  
  414. recv_1:
  415.               cmp     cs:is_186,0
  416.               jne     recv11
  417.               jmp     read_b_mode
  418. ;
  419. ;        read packet out in word mode
  420. ;
  421. recv11:
  422.     mov    dx,cs:[io_adr]    ; get status and reserved byte
  423.     add    dx,BMPR_MEM_PORT
  424.     in    ax,dx
  425.     in    ax,dx                           ; get packet size
  426.     inc    ax                              ; convert to words
  427.     and    ax,not 1                        ; save it for copy out...
  428.     push    ax
  429.                     ;read first 14 bytes from receive buffer into ether_buff
  430.     mov    ax,cs
  431.     mov    es, ax
  432.     mov    di,offset ether_buff
  433.     mov    cx,16/2                            ; word mode, remember...
  434.     cld
  435. ;    rep    insw            ; read words into ether_buff
  436.     db    0f3h, 06dh    ;masm 4.0 doesn't grok "rep insw"
  437.  
  438. ;
  439. ;      If the sender is myself, ignore the packet.  This allows async
  440. ;      send/receive without messing up...
  441. ;
  442.     mov    si,offset ether_buff+EADDR_LEN       ; we want the SOURCE
  443.     mov    dx,cs:io_adr
  444.     add    dx,PROM_ID
  445.     mov    cx,EADDR_LEN
  446. my_send:
  447.     in    al, dx
  448.     inc    dx
  449.     cmp    al,byte ptr ds:[si]
  450.     jne    not_mine
  451.     inc    si
  452.     loop    my_send
  453.     jmp    word_flush                      ; mine, so flush it
  454. ;
  455. ;      cx = length, es:di = pointer to ethertype
  456. ;
  457. not_mine:
  458.     pop    cx
  459.     push    cx
  460.     mov    di,offset ether_type
  461.     mov    ax,cs
  462.     mov    es,ax            ; es:di -> ether type, cx = size# bytes
  463.     mov    dl, BLUEBOOK        ;assume bluebook Ethernet.
  464.     mov    ax, es:[di]
  465.     xchg    ah, al
  466.     cmp     ax, 1500
  467.     ja    BlueBookPacket
  468.     inc    di            ;set di to 802.2 header
  469.     inc    di
  470.     mov    dl, IEEE8023
  471. BlueBookPacket:
  472.     call    recv_find        ; got a buffer?
  473.     mov    ax,es
  474.     or    ax,di            ; pointer zero?
  475.     je    word_flush        ; no pointer, discard data
  476. ;
  477. ;      es:di -> users buffer, do copy...
  478. ;      ds:si -> source of copy
  479. ;
  480.     mov    cs:[usr_ptr.segm],es; save ULP pointer
  481.     mov    cs:[usr_ptr.offs],di
  482.     mov    ax,cs
  483.     mov    ds,ax
  484.     mov    si,offset ether_buff    ; copy header to users buffer
  485.     mov    cx,16/2            ; 8 words to copy
  486.     cld
  487.     rep    movsw
  488.     mov    dx,cs:[io_adr]        ;copy rest of data to user
  489.     add    dx,BMPR_MEM_PORT    ; buffer in es:di ->
  490.     pop    cx
  491.     push    cx
  492.     sub    cx,16
  493.     shr    cx,1
  494.     cld
  495. ;    rep    insw            ; read word, store at es:di ->
  496.     db    0f3h, 06dh    ;masm 4.0 doesn't grok "rep insw"
  497.     pop    cx            ;call recv_copy to say copy done
  498.     lds    si,cs:[usr_ptr]
  499.     call    recv_copy
  500.     jmp    recv_0            ; go get another packet
  501. word_flush:
  502.     mov    dx,cs:[io_adr]
  503.     add    dx,BMPR_MEM_PORT
  504.     pop    cx
  505.     sub    cx,16            ; adjust word count
  506.     shr    cx,1
  507. word_f:
  508.     in    ax,dx
  509.     loop    word_f
  510.     jmp    recv_0
  511. ;
  512. ;             go see of any more packets comming....
  513. ;
  514. ;             READ in BYTE MODE
  515. ;
  516. read_b_mode:
  517.     mov    dx,cs:[io_adr]    ;get status and reserved byte
  518.     add    dx,BMPR_MEM_PORT
  519.     in    al,dx        ; vacuum status and reserved
  520.     in    al,dx
  521.     in    al,dx        ; get packet size
  522.     xchg    al,ah        ; low byte in ah
  523.     in    al,dx        ; get packet size
  524.     xchg    al,ah        ; fix size ah/al order
  525.     push    ax        ; keep number of bytes
  526.     ;      read first 16 bytes from receive buffer into ether_buff
  527.     mov    ax,cs
  528.     mov    es,ax
  529.     mov    di,offset ether_buff
  530.     mov    cx,16            ; byte mode, 16 byte header
  531.     cld
  532. rdb:
  533.     in    al,dx            ; read 16 bytes into ether_buff
  534.     stosb
  535.     loop    rdb
  536. ;
  537. ;      If the sender is myself, ignore the packet.
  538. ;
  539.     mov    si,offset ether_buff+EADDR_LEN; we want the SOURCE...
  540.     mov    dx,cs:[io_adr]
  541.     add    dx,PROM_ID
  542.     mov    cx,EADDR_LEN
  543. my_sendb:
  544.     in    al,dx
  545.     inc    dx
  546.     cmp    al,byte ptr ds:[si]
  547.     jne    not_mineb
  548.     inc    si
  549.     loop    my_sendb
  550.     jmp    byte_flush                  ; mine, so flush it
  551. ;
  552. ;      cx = length, es:di = pointer to ethertype
  553. ;
  554. not_mineb:
  555.     pop    cx
  556.     push    cx
  557.     mov    di,offset ether_type
  558.     mov    ax,cs
  559.     mov    es,ax             ; es:di -> ether type, cx = size#bytes
  560.     mov    dl, BLUEBOOK        ;assume bluebook Ethernet.
  561.     mov    ax, es:[di]
  562.     xchg    ah, al
  563.     cmp     ax, 1500
  564.     ja    BlueBookPacket1
  565.     inc    di            ;set di to 802.2 header
  566.     inc    di
  567.     mov    dl, IEEE8023
  568. BlueBookPacket1:
  569.     call    recv_find                   ; got a buffer?
  570.     mov    ax,es
  571.     or    ax,di                       ; pointer zero?
  572.     je    byte_flush                  ; no pointer, discard data
  573. ;
  574. ;      es:di -> users buffer, do copy...
  575. ;      ds:si -> source of copy
  576. ;
  577.     mov    cs:[usr_ptr.segm],es    ; save ULP pointer
  578.     mov    cs:[usr_ptr.offs],di
  579.     mov    ax,cs
  580.     mov    ds,ax
  581.     mov    si,offset ether_buff        ; copy header to users buffer
  582.     mov    cx,16                       ; 16 bytes in header to copy
  583.     cld
  584.     rep
  585.     movsb
  586.     mov    dx,cs:io_adr     ; copy rest of data to users
  587.     add    dx,BMPR_MEM_PORT            ; buffer in es:di ->
  588.     pop    cx
  589.     push    cx
  590.     sub    cx,14
  591.     cld
  592. cpyb:
  593.     in    al,dx            ; read byte
  594.     stosb                ; store at es:di ->
  595.     loop    cpyb
  596.     pop    cx            ; call recv_copy to say copy done
  597.     lds    si,cs:[usr_ptr]
  598.     call    recv_copy
  599.     jmp    recv_0            ; go get another packet...
  600. byte_flush:
  601.     mov    dx,cs:io_adr
  602.     add    dx,BMPR_MEM_PORT
  603.     pop    cx
  604.     sub    cx,16            ; adjust byte count header
  605. byte_f:
  606.     in    al,dx
  607.     loop    byte_f
  608.     jmp    recv_0            ; go to see if any more packets comming...
  609. recv_99:
  610. ;      receive ok, restore recive mask and exit
  611. ;
  612.     writebport    DLCR_RECV_MASK,en_rcv_irqs
  613.     ret
  614.  
  615.  
  616.     public    recv_exiting
  617. recv_exiting:
  618. ;called from the recv is after interrupts have been acknowledged.
  619. ;Only ds and ax have been saved.
  620. ;
  621.     assume    ds:nothing
  622.     ret
  623.  
  624. ;any code after this will not be kept after initialization.
  625.  
  626. end_resident    label    byte
  627.  
  628. io_adr_msg    db    "I/O Base Address: ",'$'
  629. int_no_msg    db    " Interrupt Level: ",'$'
  630. no_card_msg    db    "INIT: No card at I/O address specified",CR,LF,'$'
  631. is_186_msg    db    "INIT: Using WORD I/O mode.",CR,LF,'$'
  632. not_186_msg    db    "INIT: Using BYTE I/O mode.",CR,LF,'$'
  633. installed_ok    db    "INIT: Installation Complete",CR,LF,'$'
  634.  
  635.     public  usage_msg
  636. usage_msg   db  "usage: TiaraFTP [-n] [-d] [-w] <packet_int_no> <int_no> <io_adr>",CR,LF,'$'
  637.  
  638.     public  copyright_msg
  639. copyright_msg    label    byte
  640.  db CR,LF
  641.  db "TiaraFTP:  Driver for Tiara Card, Version ",'0'+(majver / 10),'0'+(majver mod 10),".",'0'+version, CR,LF
  642.  db "         - for PC, PC-AT, and Micro Channel (IBM tm)",CR,LF
  643.  db "portions - Copyright 1990, 1991 Queens University",CR,LF
  644.  db "    Written by Brian Fisher",CR,LF
  645.  db CR,LF,'$'
  646.  
  647.     extrn   set_recv_isr: near
  648. ;enter with si-> argument string,di->wword to store.
  649. ;if there is no number, don't change  the number.
  650.  
  651. ;enter with si -> argument string, di -> word to store.
  652. ;if there is no number, don't change the number.
  653.     extrn   get_number: near
  654.  
  655. ;enter with dx -> name of word, di -> dword to print.
  656.     extrn    print_number: near
  657.  
  658.  
  659. ;==============================================================================;
  660. ;========================= MICROCHANNEL SUPPORT ===============================;
  661. ;==============================================================================;
  662.  
  663. POS_max         equ     7h              ; max number of slots to check
  664.  
  665. POS_select      equ     096h            ; POS Select register location
  666. POS_mask        equ     008h            ; POS Select mask
  667.  
  668. POS_0           equ     100h            ; POS Registers
  669. POS_1           equ     101h
  670. POS_2           equ     102h
  671.  
  672. ;       Card Specific Items
  673.  
  674. Adapter_ID      equ     6001h           ; POS_0 | POS_1
  675.  
  676. Adapter_open    equ     00000001b       ; POS_2
  677. ;                       ||||||||
  678. ;                       |||||||+-------- 1 = card enabled (open)
  679. ;                       ||||||+--------- 1 = Boot Prom Enable
  680. ;                       |||||+---------- } IRQ Level Select
  681. ;                       ||||+----------- } IRQ Level Select
  682. ;                       |||+------------ )
  683. ;                       ||+------------- ) I/O Port Base Address Select
  684. ;                       |+-------------- )
  685. ;                       +--------------- )
  686.  
  687. ; Adapter Boot PROM is disabled for this configuration, so POS_5 has no
  688. ; meaning, and is ignored.
  689.  
  690. irq_list       dw       3              ;  00h    POS_2 after [POS_2]&0Ch
  691.                dw       4              ;  04h
  692.                dw       7              ;  08h
  693.                dw       9              ;  0Ch
  694.  
  695. io_list        dw       1200h          ; MCH I/O Address List
  696.                dw       1220h
  697.                dw       1240h
  698.                dw       1260h
  699.                dw       1280h
  700.                dw       12A0h
  701.                dw       12C0h
  702.                dw       12E0h
  703.                dw       1300h
  704.                dw       1320h
  705.                dw       1340h
  706.                dw       1360h
  707.                dw       1380h
  708.                dw       13A0h
  709.                dw       13C0h
  710.                dw       13E0h
  711.  
  712. mch_found      db      "INIT: This machine has a MICROCHANNEL card.",CR,LF,'$'
  713.  
  714.  
  715.     public  parse_args
  716. parse_args:
  717. ;
  718. ;      Look for MicroChannel POS information, and if found, set default
  719. ;      values for I/O base address and IRQ level before parsing the
  720. ;      command line.
  721. ;
  722.         pushf                  ; save flags
  723.         cli                    ; no IRQ's during this phase
  724.  
  725.         mov     cx,POS_max+1   ; start with the last slot first...
  726.         mov     dx,POS_select
  727.         in      al,dx          ; Save old POS_select value
  728.         push    ax
  729.  
  730. mch_chk:
  731.         mov     al,cl          ; get slot count
  732.         dec     al             ; adjust it
  733.         or      al,POS_mask    ; add the mask
  734.         mov     dx,POS_select
  735.         out     dx,al          ; write select value
  736.  
  737.         mov     dx,POS_1       ; read the Adapter_id
  738.         in      al,dx          ; get hi byte
  739.         xchg    al,ah
  740.         dec     dx
  741.         in      al,dx          ; get lo byte
  742.         cmp     ax,Adapter_id  ; did I find the card?
  743.         je      mch_chk_match  ; yes...
  744.         loop    mch_chk
  745.  
  746. ;       use this to leave microchannel POS_select as we found it...
  747.         pop     ax
  748.         mov     dx,POS_select
  749.         out     dx,al
  750.         popf
  751.         jmp     parse_start
  752.  
  753. mch_chk_match:
  754. ;       parse I/O base address and interrupt level from POS_2 data
  755.         mov     dx,POS_2
  756.         in      al,dx
  757. ;
  758. ;       determine interrupt level
  759.         and     al,0Ch                  ; bits 2,3 are IRQ level
  760.         mov     cl,1
  761.         shr     al,cl                   ; index for irq_list
  762.         xor     ah,ah
  763.         mov     bx,ax
  764.         mov     ax,word ptr [bx+offset irq_list]
  765.         mov     word ptr int_no,ax
  766.  
  767.         in      al,dx                   ; read POS_2 again
  768.         and     al,0F0h                 ; get index into io_list
  769.         mov     cl,3
  770.         shr     al,cl
  771.         xor     ah,ah
  772.         mov     bx,ax
  773.         mov     ax,word ptr [bx+offset io_list]
  774.         mov     word ptr io_adr,ax
  775.  
  776.         pop     ax
  777.         mov     dx,POS_select
  778.         out     dx,al
  779.         popf
  780.         print$  mch_found
  781.  
  782. parse_start:
  783.  
  784. ;      parse  hardware interrupt number and I/O base address from the
  785. ;      command line.
  786. ;
  787.     mov    bx,offset int_no_msg    ; interrupt level?
  788.     mov    di,offset int_no
  789.     call    get_number
  790.     jc    _parse_exit
  791.     mov    bx,offset io_adr_msg    ; first comes the I/O base address
  792.     mov    di,offset io_adr
  793.     call    get_number
  794. _parse_exit:
  795.     clc
  796.     ret
  797.  
  798. ;==============================================================================;
  799. ;==================== MICROCHANNEL SUPPORT ENDS ===============================;
  800. ;==============================================================================;
  801.  
  802.     public etopen
  803. etopen:
  804.     writebport    DLCR_ENABLE,card_disable    ; disable etherstar
  805.     writebport    DLCR_XMIT_STAT,clear_status    ; clr xmit status
  806.     writebport    DLCR_XMIT_MASK,no_tx_irqs    ; disable xmit IRQ's
  807.     writebport    DLCR_RECV_STAT,clr_rcv_status    ; clear rcv status
  808.     writebport    DLCR_RECV_MASK,en_rcv_irqs    ; enable rcv IRQ's
  809.     writebport    DLCR_XMIT_MODE,xmit_mode    ; set xmit mode
  810.     writebport    DLCR_RECV_MODE,recv_mode    ; set receive mode
  811. ;
  812. ;      Set Node ID:
  813. ;
  814.     mov    cx,EADDR_LEN        ; calc base of I/O regs for node id
  815.     mov    bx,cs:io_adr
  816.     mov    dx,bx
  817.     add    bx,DLCR_NODE_ID
  818.     add    dx,PROM_ID        ; and base of PROM for copy
  819. etopen0:
  820.     in    al,dx            ; read byte of factory address
  821.     xchg    bx,dx
  822.     out    dx,al            ; write to register
  823.     xchg    bx,dx
  824.     inc    dx
  825.     inc    bx
  826.     loop    etopen0            ; until copy is done...
  827. ;
  828. ;      Verify card exists by comparing address to PROM
  829. ;
  830.     mov    cx,EADDR_LEN
  831. etopen1:
  832.     dec    dx
  833.     dec    bx
  834.     in    al,dx
  835.     xchg    bx,dx
  836.     mov    ah,al
  837.     in    al,dx
  838.     xchg    bx,dx
  839.     cmp    al,ah
  840.     jne    etopen_nocard        ; no card found
  841.     loop    etopen1
  842.  
  843. ;Determine the processor type.  The 8088 and 8086 will actually shift ax
  844. ;over by 33 bits, while the 80[123]86 use a shift count mod 32.
  845.  
  846.     mov    cl,33
  847.     mov    ax,0ffffh
  848.     shl    ax,cl            ; Thanks to Russ Nelson for this little
  849.     jz    not_186            ; bit of 'clip art'.
  850.     mov    is_186,1
  851.     print$    is_186_msg
  852.     jmp    etopen2
  853. not_186:
  854.     print$  not_186_msg
  855. etopen2:
  856.                     ; vacuum data port until BUF_EMPTY
  857.     mov    dx,cs:io_adr
  858.     mov    bx,dx
  859.     add    bx,DLCR_RECV_MODE
  860.     add    dx,BMPR_MEM_PORT
  861.     cmp    cs:is_186,0
  862.     je    vac_88
  863. vac_86:
  864.     in    ax,dx
  865.     xchg    dx,bx
  866.     in    ax,dx
  867.     xchg    dx,bx
  868.     test    al,BUF_EMPTY
  869.     jz    vac_86
  870.     jmp    all_done
  871. vac_88:
  872.     in    al,dx
  873.     xchg    dx,bx
  874.     in    al,dx
  875.     xchg    dx,bx
  876.     test    al,BUF_EMPTY
  877.     jz    vac_88
  878. all_done:
  879.     writebport    DLCR_ENABLE,card_enable
  880.     call    set_recv_isr                ; install receive IRQ routine
  881.  
  882.     mov    al, int_no        ; Get board's interrupt vector
  883.     add    al, 8
  884.     cmp    al, 8+8            ; Is it a slave 8259 interrupt?
  885.     jb    set_int_num        ; No.
  886.     add    al, 70h - 8 - 8        ; Map it to the real interrupt.
  887. set_int_num:
  888.     xor    ah, ah            ; Clear high byte
  889.     mov    int_num, ax        ; Set parameter_list int num.
  890.  
  891.     print$    installed_ok                ; if all is okay,
  892.     mov    dx,offset end_resident
  893.     clc
  894.     ret
  895. etopen_nocard:
  896.     print$  no_card_msg              ; couldn't verify card exists...
  897.     stc
  898.     ret
  899.  
  900.     public    print_parameters
  901. print_parameters:
  902. ;echo our command-line parameters
  903.     mov    di,offset io_adr    ; first comes the I/O base address
  904.     mov    dx,offset io_adr_msg
  905.     call    print_number
  906.     mov    di,offset int_no    ; interrupt level?
  907.     mov    dx,offset int_no_msg
  908.     call    print_number
  909.     ret
  910.  
  911. code    ends
  912.  
  913.     end
  914.